﻿#include "OiPCH.hpp"
#include <QGraphicsScene>
#include <QtCharts/QValueAxis>
#include <QCursor>

using namespace QtCharts;

namespace Oi
{
    namespace PLScannerCore
    {
// 
//         class RoiRect : public QGraphicsItem
//         {
//         public:
//             QRectF boundingRect() const;
//             RoiRect(ProfileView *view, QGraphicsItem *parent = nullptr);
//             ~RoiRect();
// 
//         public:
//             QPointF mapFromChart(const QPointF p) const
//             {
//                 return _view->chart()->mapToScene(_view->chart()->mapToPosition(p));
//             }
// 
//             QPointF mapToChart(const QPointF p) const
//             {
//                 return _view->chart()->mapToValue(_view->chart()->mapFromScene(p));
//             }
// 
//             QRectF mapFromChart(const QRectF r) const
//             {
//                 auto p1 = mapFromChart(r.topLeft());
//                 auto p2 = mapFromChart(r.bottomRight());
// 
//                 return QRectF(p1, p2).normalized();
//             }
// 
//             QRectF mapToChart(const QRectF r) const
//             {
//                 auto p1 = mapToChart(r.topLeft());
//                 auto p2 = mapToChart(r.bottomRight());
// 
//                 return QRectF(p1, p2).normalized();
//             }
// 
//         protected:
//             void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
//             void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
//             void mousePressEvent(QGraphicsSceneMouseEvent *event);
//             void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
//             void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
// 
//         public:
//             ProfileView * _view;
// 
//         public:
//             bool _displayRoi;
//             QRectF _roi;
// 
//         public:
//             int _touchId;
//             int _moveId;
//         };
// 
//         QRectF RoiRect::boundingRect() const
//         {
//             return scene() ? scene()->sceneRect().adjusted(10000, 10000, -10000, -10000) : QRectF();
//         }
// 
//         RoiRect::RoiRect(ProfileView *view, QGraphicsItem *parent /*= Q_NULLPTR*/)
//             : QGraphicsItem(parent)
//         {
//             _view = view;
//             _touchId = 0;
//             _moveId = 0;
// 
//             _displayRoi = !PLScanner::instance()->fullROI;
//             if(_displayRoi)
//             {
//                 Math::Point2d p1 = Math::Point2d(PLScanner::instance()->roiX, PLScanner::instance()->roiY);
//                 Math::Point2d p2 = Math::Point2d(p1.x() + PLScanner::instance()->roiWidth, p1.y() + PLScanner::instance()->roiHeight);
// 
//                 auto p3 = Calib::OiCalib()->toWorld(p1);
//                 auto p4 = Calib::OiCalib()->toWorld(p2);
// 
//                 double roiX1 = qMin(p3.x(), p4.x()) * 1e3;
//                 double roiX2 = qMax(p3.x(), p4.x()) * 1e3;
// 
//                 double roiY1 = qMin(p3.z(), p4.z()) * 1e3;
//                 double roiY2 = qMax(p3.z(), p4.z()) * 1e3;
// 
// //                 auto p5 = mapFromChart(QPointF(roiX1, roiY1));
// //                 auto p6 = mapFromChart(QPointF(roiX2, roiY2));
// 
//                 _roi = QRectF(QPointF(roiX1, roiY1), QPointF(roiX2, roiY2));
//             }
//         }
// 
//         RoiRect::~RoiRect()
//         {
//             if(_displayRoi && _roi.isEmpty())
//             {
//                 auto  p5 = _roi.topLeft();
//                 auto  p6 = _roi.bottomRight();
// 
//                 Math::Point2d p1 = Math::Point2d(p5.x() / 1e3, p5.y() / 1e3);
//                 Math::Point2d p2 = Math::Point2d(p6.x() / 1e3, p6.y() / 1e3);
// 
//                 auto p3 = Calib::OiCalib()->toImage(p1);
//                 auto p4 = Calib::OiCalib()->toImage(p2);
// 
//                 double roiX1 = qMin(p3.x(), p4.x());
//                 double roiX2 = qMax(p3.x(), p4.x());
// 
//                 double roiY1 = qMin(p3.y(), p4.y());
//                 double roiY2 = qMax(p3.y(), p4.y());
// 
//                 PLScanner::instance()->roiX = roiX1;
//                 PLScanner::instance()->roiY = roiY1;
// 
//                 PLScanner::instance()->roiWidth = roiX2 - roiX1;
//                 PLScanner::instance()->roiHeight = roiY2 - roiY1;
//             }
//         }
// 
//         void RoiRect::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
//         {
//             _touchId = 0;
// 
//             auto sp = event->pos();
// 
//             auto roi = mapFromChart(_roi);
// 
//             QRectF tRect(QPointF(_roi.left(), _roi.top() - 3), QPointF(_roi.right(), _roi.top() + 3));
//             QRectF lRect(QPointF(_roi.left() - 3, _roi.top()), QPointF(_roi.left() + 3, _roi.bottom()));
//             QRectF bRect(QPointF(_roi.left(), _roi.bottom() - 3), QPointF(_roi.right(), _roi.bottom() + 3));
//             QRectF rRect(QPointF(_roi.right() - 3, _roi.top()), QPointF(_roi.right() + 3, _roi.bottom()));
// 
//             if(tRect.contains(sp))
//             {
//                 _touchId = 1;
//             }
//             else if(lRect.contains(sp))
//             {
//                 _touchId = 3;
//             }
//             else if(bRect.contains(sp))
//             {
//                 _touchId = 2;
//             }
//             else if(rRect.contains(sp))
//             {
//                 _touchId = 4;
//             }
// 
//             if(_touchId > 0)
//             {
//                 setCursor(_touchId <= 2 ? Qt::SplitVCursor : Qt::SplitHCursor);
//             }
//             else
//             {
//                 setCursor(Qt::ArrowCursor); event->setAccepted(false);
//             }
// 
//         }
// 
//         void RoiRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
//         {
//             if(event->button() & Qt::LeftButton)
//             {
//                 _moveId = _touchId;
//             }
//             else
//             {
//                 event->setAccepted(false);
//             }
//         }
// 
//         void RoiRect::mousePressEvent(QGraphicsSceneMouseEvent *event)
//         {
//             if(event->button() & Qt::LeftButton)
//             {
//                 auto sp = event->pos();
// 
//                 if(_moveId == 1)
//                 {
//                     _roi.setTop(sp.y());
//                 }
//                 else if(_moveId == 2)
//                 {
//                     _roi.setBottom(sp.y());
//                 }
//                 else if(_moveId == 3)
//                 {
//                     _roi.setLeft(sp.x());
//                 }
//                 else if(_moveId == 4)
//                 {
//                     _roi.setRight(sp.x());
//                 }
//             }
//             else
//             {
//                 event->setAccepted(false);
//             }
//         }
// 
//         void RoiRect::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
//         {
//             QGraphicsItem::mouseReleaseEvent(event);
//         }
// 
//         void RoiRect::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
//         {
//             painter->setPen(QPen(_touchId > 0 ? Qt::red : Qt::green, 2));
//             painter->drawRect(_roi);
//         }
// 

        class ProfileViewImpl : public Impl<ProfileView>
        {
        public:
            void init();
            void exit();

        public:
            ProfilesChart* _chart;
            QGraphicsScene* _scene;

        public:
            Qt::CursorShape _cursor;
            bool _isDrag;
            QPoint _dragPoint;

//         public:
//             RoiRect* _roiItem;
        };

        void ProfileViewImpl::init()
        {
            OI_Q(ProfileView);

            _isDrag = false;

            _cursor = Qt::ArrowCursor;

            _scene = new QGraphicsScene();
            _scene->setBackgroundBrush(PLScannerStyle::ChartBgColor());
            q->setScene(_scene);
            q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
            q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

            _chart = new ProfilesChart();
            _chart->legend()->hide();
            _chart->setFlag(QGraphicsItem::ItemIsSelectable, true);

            QValueAxis* pXAxis = new QValueAxis();
            pXAxis->setRange(-100, 100);
            pXAxis->setGridLinePen(QColor::fromRgb(50, 50, 50));
            _chart->setAxisX(pXAxis);

            QValueAxis* pYAxis = new QValueAxis();
            pYAxis->setRange(0, 10);
            pYAxis->setGridLinePen(QColor::fromRgb(50, 50, 50));
            _chart->setAxisY(pYAxis);

            _chart->layout()->setContentsMargins(0, 0, 0, 0);
            _chart->setBackgroundRoundness(0);

//             _chart->axisX()->setGridLineVisible(true);
//             _chart->axisY()->setGridLineVisible(true);
//             _chart->axisX()->setMinorGridLineVisible(true);

            _scene->addItem(_chart);

//            _roiItem = new RoiRect(q);
//            _scene->addItem(_roiItem);
//            _roiItem->setVisible(_roiItem->_displayRoi);

            _scene->setSceneRect(1.0 * INT_MIN, 1.0 * INT_MIN, 2.0 * INT_MAX, 2.0 * INT_MAX);

            q->setRenderHint(QPainter::Antialiasing);

            q->setDragMode(QGraphicsView::RubberBandDrag);
            q->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        }

        void ProfileViewImpl::exit()
        {

        }

        ProfileView::ProfileView(QWidget *parent)
            : QGraphicsView(parent)
        {
            OI_I(ProfileView)->init();
        }

        ProfileView::~ProfileView()
        {
            OI_I(ProfileView)->exit();
        }

        ProfilesChart* ProfileView::chart()
        {
            return OI_IMPL()->_chart;
        }

        void ProfileView::zoomFit()
        {
            OI_F(ProfileView);
            d->_chart->setGeometry(0, 0, viewport()->width(), viewport()->height());
            fitInView(d->_chart, Qt::KeepAspectRatio);
        }

        void ProfileView::resizeEvent(QResizeEvent *event)
        {
            zoomFit();
        }

        void ProfileView::mousePressEvent(QMouseEvent *event)
        {
            OI_F(ProfileView);
            if(event->button() & Qt::MiddleButton)
            {
                d->_cursor = this->cursor().shape();
                setCursor(Qt::OpenHandCursor);
                d->_isDrag = true;
                d->_dragPoint = event->pos();

                event->accept();
                return;
            }

            QGraphicsView::mousePressEvent(event);
        }

        void ProfileView::mouseMoveEvent(QMouseEvent* event)
        {
            OI_F(ProfileView);

            if( event->buttons() & Qt::MiddleButton )
            {
                if(d->_isDrag)
                {
                    d->_chart->scroll(d->_dragPoint.x() - event->x(), event->y() - d->_dragPoint.y());
                    d->_dragPoint = event->pos();

                    event->accept();

                    return;
                }
            }

            QGraphicsView::mouseMoveEvent(event);
        }

        void ProfileView::mouseReleaseEvent(QMouseEvent* event)
        {
            OI_F(ProfileView);

            if(event->button() & Qt::MiddleButton)
            {
                setCursor(d->_cursor);
                d->_isDrag = false;

                event->accept();
                return;
            }

            QGraphicsView::mouseReleaseEvent(event);
        }

        void ProfileView::mouseDoubleClickEvent(QMouseEvent* event)
        {
            OI_F(ProfileView);

            if (event->button() & Qt::MouseEventCreatedDoubleClick)
            {
                d->_chart->autoRange();
            }

            QGraphicsView::mouseDoubleClickEvent(event);
        }

        void ProfileView::paintEvent(QPaintEvent *event)
        {
            QGraphicsView::paintEvent(event);
        }

        void ProfileView::wheelEvent(QWheelEvent *event)
        {
            OI_F(ProfileView);
            if(event->delta() > 0)
            {
                d->_chart->zoom(1.1);
            }
            else
            {
                d->_chart->zoom(10.0 / 11);
            }
        }
    }
}
